﻿using SharpSoft.Lexing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharpSoft.Documentation.Html.CSS
{
    /// <summary>
    /// Css属性集合词法分析器
    /// </summary>
    internal class CssPropertiesLexer : _TextLexer
    {
        public CssPropertiesLexer(TextSource source)
            : base(source)
        {
        }
        public CssPropertiesLexer(string source)
            : base(source)
        {

        }

        public CssPropertiesToken ReadToken()
        {
            SkipWhiteSpace();
            if (EOS())
                return null;
            char c = Current;
            char p = Peek();
            int pos = Position;
            if (c == '/' && p == '*')
            {
                SkipComment();
                SkipWhiteSpace();
                c = Current;
                p = Peek();
            }
            if (c == ':')//值开始
            {
                Next();
                string value = ReadPropertyValue();
                return new CssPropertiesToken(pos, value.Length, CssPropertiesTokenType.PropertyValue, value);
            }
            else
            {
                if (c == ';')
                {
                    Next();
                    SkipWhiteSpace();
                    SkipComment();
                    SkipWhiteSpace();
                }
                string name = ReadPropertyName();
                if (name == null)//注意：此处为null才表示属性块结束，为空字符只是说明词法有异常。此处不做处理。外围断言属性名为空再抛出异常
                {
                    return null;
                }
                return new CssPropertiesToken(pos, name.Length, CssPropertiesTokenType.PropertyName, name);
            }

        }
        /// <summary>
        /// 从当前位置读取属性名称
        /// </summary>
        /// <returns></returns>
        private string ReadPropertyName()
        {
            SkipWhiteSpace();//跳过空白
            char c = Current;
            StringBuilder sb = new StringBuilder(50);
            while (!EOS())
            {
                if (c == ':')//属性名称结束 
                    return sb.ToString();
                if (c.IsIdentifier() || c == '-')
                {
                    sb.Append(c);
                    c = Next();
                }
                else if (c.IsWhiteSpace())
                {
                    SkipWhiteSpace();
                    c = Current;
                    if (c != ':')
                    {
                        throw new CssSyntaxException(Position, 1, "属性名称之后未找到值分隔符冒号（:）。");
                    }
                    
                }
                else
                {
                    throw new CssSyntaxException(Position, 1, "属性名称中出现意外的字符：[" + c + "]。");
                }
            }
            if (sb.ToString().Length > 0)
                throw new Exception("属性名称未找到结束标识符。");
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 从当前位置读取值
        /// </summary>
        /// <returns></returns>
        private string ReadPropertyValue()
        {
            SkipWhiteSpace();//跳过空白
            char c = Current;
            StringBuilder sb = new StringBuilder(100);
            while (!EOS())
            {
                if (c == '\'' || c == '"')
                    sb.Append(ReadString());
                else if (c == ';' || c=='\n' || c=='\r')//属性结束 
                    break;
                else
                    sb.Append(c);
                c = Next();
            }
            return sb.ToString();
        }

        /// <summary>
        /// 跳过注释
        /// </summary>
        private void SkipComment()
        {
            char c = Current;
            char p = Peek();
            if (c == '/' && p == '*')
            {
                Next();
                while (!EOS())
                {
                    c = Next();
                    p = Peek();
                    if (c == '*' && p == '/')
                    {
                        Next(2);
                        return;//注释结束
                    }
                }
            }
            else//此位置不是注释
            {
                return;
            }
            throw new Exception("注释未正常闭合。");
        }
    }
}
